﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Drawing;
using System.Xml.XPath;

namespace SLRT.dao.data
{
    public class Database
    {
        public static FileInfo LETTERS_XML_FILE = new FileInfo(@"../../db/letters/letters.xml");
        public static FileInfo WORDS_XML_FILE = new FileInfo(@"../../db/dictionary/dictionary.xml");
        private List<Letter> letters;
        private List<Word> words;

        public Database()
        {
        }

        public void load()
        {
            XMLparseLetters();
            XMLparseWords();

                
            letters.ForEach(letter =>
            {
                if (letter != null)
                {
                    IEnumerable<FileInfo> files= letter.DirPath.Directory.EnumerateFiles(); // dubaş

                    List<DBImage> dbImages = new List<DBImage>();

                    files.ToList<FileInfo>().ForEach(file => 
                    {
                        dbImages.Add(DBImage.loadFromDisk(file));
                    });

                    letter.DBImages = dbImages;

                }
            });
        }

        /**
        * Parse XMLs of Letters and Words.
        * Then process bmp/jpg images from disk and load the processed images to memory.
        */
        public void process() 
        {
            this.XMLparseLetters();
            this.XMLparseWords();

            if (this.letters == null) 
            {
                Console.WriteLine("Error: Database.letters = null\n");
                return;
            }

            letters.ForEach(point =>
            {
                if (point != null)
                {
                    FileInfo dirPath = point.DirPath;
                    //FileInfo[] files = dirPath.listFiles(new DBImageFileFilter());

                    FileInfo[] files = (FileInfo[])dirPath.Directory.EnumerateFiles(); // dubaş

                    List<DBImage> dbImages = new List<DBImage>();

                    for (int i = 0; i < files.Length; i++)
                    {
                        dbImages.Add(DBImage.loadRawFromDisk(files[i]));
                    }
                    
                    point.DBImages = dbImages;

                }
            });
        }

        /**
        * Save processed DB images that are in memory to disk.
        */
        public void save() 
        {
            if (this.letters == null) 
            {
                Console.WriteLine("Error: Database.letters = null\n");
                return;
            }

            letters.ForEach(point =>
            {
                if (point != null)
                {
                    FileInfo dirPath = point.DirPath;
                    

                    point.DBImages.ForEach(point2 =>
                        {
                            int i = 0;

                            if (point2 != null)
                            {
                                FileInfo file = new FileInfo(dirPath.FullName + "/" + i + "dbim");
                                point2.saveToDisk(file);

                                i++;
                            }

                        });

                }
            });
        }

        private void XMLparseLetters()
        {
            this.letters = new List<Letter>();
            XmlDocument doc = new XmlDocument();
            doc.Load(LETTERS_XML_FILE.FullName);
            XPathNavigator navigator = doc.CreateNavigator();
            navigator.MoveToRoot();

            if (navigator.MoveToFirstChild())
            {
                if (navigator.MoveToFirstChild())
                {
                    do
                    {
                        String letterName = String.Empty;
                        String letterPath = String.Empty;
                        if (navigator.MoveToChild("name", String.Empty))
                        {
                            letterName = navigator.Value;
                            navigator.MoveToParent();
                        }

                        if (navigator.MoveToChild("path", String.Empty))
                        {
                            letterPath = navigator.Value;
                            navigator.MoveToParent();
                        }
                        
                        if (!letterName.Equals(String.Empty) && !letterPath.Equals(String.Empty))
                        {
                            Letter letter = new Letter(letterName, new FileInfo(letterPath));
                            letters.Add(letter);
                        }
                    }

                    while (navigator.MoveToNext());
                }
            }

        }

        private void XMLparseWords() 
        {

            this.words = new List<Word>();
            XmlDocument doc = new XmlDocument();
            doc.Load(WORDS_XML_FILE.FullName);
            XPathNavigator navigator = doc.CreateNavigator();
            navigator.MoveToRoot();

            if (navigator.MoveToFirstChild())
            {
                if (navigator.MoveToFirstChild())
                {
                    do
                    {
                        String wordName = String.Empty;
                        String wordPath = String.Empty;
                        if (navigator.MoveToChild("name", String.Empty))
                        {
                            wordName = navigator.Value;
                            navigator.MoveToParent();
                        }

                        if (navigator.MoveToChild("path", String.Empty))
                        {
                            wordPath = navigator.Value;
                            navigator.MoveToParent();
                        }

                        if (!wordName.Equals(String.Empty) && !wordPath.Equals(String.Empty))
                        {
                            Word word= new Word(wordName, new Bitmap(wordPath));
                            words.Add(word);
                        }
                    }

                    while (navigator.MoveToNext());
                }
            }

        }

        /**
        * Generates the Xml that contains the information for Letter objects
        */
        public static void generateLettersXML() 
        {
            String letter;

            try 
            {
                //BufferedReader br = new BufferedReader(new FileReader(new File("src/db/letters/letters.txt")));

                FileInfo letterReader = new FileInfo(@"../../db/letters/letters.txt");

                try 
                {
                    XmlWriter writer = XmlWriter.Create(LETTERS_XML_FILE.OpenWrite());

                    writer.WriteStartElement("letters");

                    while ((letter = letterReader.OpenRead().ReadByte().ToString()) != null)
                    {
                        writer.WriteStartElement("letter");
                        writer.WriteElementString("name", letter);
                        writer.WriteElementString("path", "/db/letters/" + letter + "/");
                        writer.WriteEndElement();
                    }

                    writer.WriteEndElement();
                    
                    writer.Flush();
                    writer.Close();
                } 
                catch (Exception e) 
                {
                    Console.WriteLine(e.Message);
                }
            } 
            catch (Exception e) 
            {
                Console.WriteLine(e.Message);
            }
        }

        /**
        * Generates the Xml that contains the information for Dictionary objects
        */
        public static void generateDictionaryXML() 
        {
            String word;

            try 
            {
                FileInfo wordRead = new FileInfo(@"../../db/dictionary/dictionary.txt");
                
                try 
                {
                    XmlWriter writer = XmlWriter.Create(WORDS_XML_FILE.OpenWrite());

                    writer.WriteStartElement("dictionary");

                    while ((word = wordRead.OpenRead().ReadByte().ToString()) != null)
                    {
                        writer.WriteStartElement("word");
                        writer.WriteElementString("name", word);
                        writer.WriteElementString("path", "src/db/dictionary/" + word + ".jpg");
                        writer.WriteEndElement();
                    }

                    writer.WriteEndElement();

                    writer.Flush();
                    writer.Close();
                }
                catch (Exception e) 
                {
                    Console.WriteLine(e.Message);
                }
            } 
            catch (Exception e) 
            {
                Console.WriteLine(e.Message);
            }
        }

        /**
        * Gets the List cotaining all the Letters parsed
        * @return the List cotaining all the Letters parsed
        */
        public List<Letter> Letters
        {
            get { return letters; }
        }

        /**
        * Gets  the List cotaining all the Words parsed
        * @return  the List cotaining all the Words parsed
        */
        public List<Word> Words
        {
            get { return words; }
        }
        
        /**
        * 
        * @param id
        * @return
        */
        public String id2String(int id) 
        {
            if (this.letters == null) 
            {
                return "_";
            }
            
            if (id - 1 < 0 || id - 1 > this.letters.Count - 1) 
            {
                return "_";
            }
            
            return this.letters.ElementAt(id - 1).LetterName;
        }
   }
}
